
#ifndef AABB2_H_
#define AABB2_H_

#include "libmath.h"
#include "Vector2.h"
#include "Transform2.h"

namespace p2 {

template<typename Real>
class Aabb2
{
public:
    inline Aabb2();
	inline bool overlaps(Aabb2<Real> const& a) const;
	inline bool contains(Aabb2<Real> const& a) const;
	inline void reset();
	inline void growToContain(Vector2<Real> const& pt);
	inline void growToContain(Aabb2<Real>& aabb);
	inline Vector2<Real> midPoint() const;
	inline Vector2<Real>& min();
	inline Vector2<Real> const& min() const;
	inline Vector2<Real>& max();
	inline Vector2<Real> const& max() const;

private:
	Vector2<Real> m_min;
	Vector2<Real> m_max;
};

template<typename Real>
Aabb2<Real>::Aabb2()
{
    reset();
}
template<typename Real>
inline void Aabb2<Real>::reset()
{
	m_min = Vector2<Real>(+Math<Real>::MAX_REAL,
		+Math<Real>::MAX_REAL);
	m_max = Vector2<Real>(-Math<Real>::MAX_REAL,
		-Math<Real>::MAX_REAL);
}

template<typename Real>
inline bool Aabb2<Real>::overlaps(Aabb2<Real> const& a) const
{
	return (a.m_min.X() <= m_max.X() && a.m_min.Y() <= m_max.Y()
		&& m_min.X() <= a.m_max.X() && m_min.Y() <= a.m_max.Y());
}

template<typename Real>
inline bool Aabb2<Real>::contains(Aabb2<Real> const& a) const
{
	return (a.m_min.X() >= m_min.X() && a.m_max.X()() <= m_max.X()
		&& a.m_min.Y() >= m_min.Y() && a.m_max.Y() <= m_max.Y());
}

template<typename Real>
inline void Aabb2<Real>::growToContain(Vector2<Real> const& pt)
{
	m_min.X() = Math<Real>::Min(m_min.X(), pt.X());
	m_min.Y() = Math<Real>::Min(m_min.Y(), pt.Y());
	m_max.X() = Math<Real>::Max(m_max.X(), pt.X());
	m_max.Y() = Math<Real>::Max(m_max.Y(), pt.Y());
}

template<typename Real>
inline void Aabb2<Real>::growToContain(Aabb2<Real>& aabb)
{
	m_min.X() = Math<Real>::Min(m_min.X(), aabb.m_min.X());
	m_min.Y() = Math<Real>::Min(m_min.Y(), aabb.m_min.Y());
	m_max.X() = Math<Real>::Max(m_max.X(), aabb.m_max.X());
	m_max.Y() = Math<Real>::Max(m_max.Y(), aabb.m_max.Y());
}

template<typename Real>
inline Vector2<Real> Aabb2<Real>::midPoint() const
{
	return (m_min + m_max) * (Real) 0.5;
}

template<typename Real>
inline Vector2<Real>& Aabb2<Real>::min()
{
	return m_min;
}

template<typename Real>
inline Vector2<Real> const& Aabb2<Real>::min() const
{
	return m_min;
}

template<typename Real>
inline Vector2<Real>& Aabb2<Real>::max()
{
	return m_max;
}

template<typename Real>
inline Vector2<Real> const& Aabb2<Real>::max() const
{
	return m_max;
}

}

#endif	//AABB2_H_
